﻿using System;

namespace AladdinGameFramework.Event
{
	internal sealed class EventManager : GameFrameworkModule, IEventManager
	{
		private readonly EventPool<GameEventAgrs> m_EventPool;

		/// <summary>
		/// 初始化事件管理器的新实例
		/// </summary>
		public EventManager()
		{
			m_EventPool = new EventPool<GameEventAgrs>(EventPoolMode.AllowNoHandler | EventPoolMode.AllowMultiHandler);
		}

		/// <summary>
		/// 获取事件数量
		/// </summary>
		public int Count
		{
			get
			{
				return m_EventPool.Count;
			}
		}

		/// <summary>
		/// 获取游戏框架模块优先级
		/// </summary>
		/// <remarks>优先级较高的会有限轮询，并且关闭的时候操作会后进行</remarks>
		internal override int Priority
		{
			get
			{
				return 100;
			}
		}

		/// <summary>
		/// 事件管理器轮询
		/// </summary>
		/// <param name="elapseSeconds">逻辑流逝时间，以秒为单位</param>
		/// <param name="realElapseSeconds">真实流逝时间，以秒为单位</param>
		internal override void Update(float elapseSeconds, float realElapseSeconds)
		{
			m_EventPool.Update(elapseSeconds, realElapseSeconds);
		}

		/// <summary>
		/// 关闭并清理事件管理器
		/// </summary>
		internal override void Shutdown()
		{
			m_EventPool.Shutdown();
		}

		/// <summary>
		/// 检查订阅事件并处理函数
		/// </summary>
		/// <param name="id">事件类型编号</param>
		/// <param name="handler">要检查的事件处理函数</param>
		/// <returns>是否存在事件处理函数</returns>
		public bool Check(int id, EventHandler<GameEventAgrs> handler)
		{
			return m_EventPool.Check(id, handler);
		}

		/// <summary>
		/// 订阅事件处理函数
		/// </summary>
		/// <param name="id">事件类型编号</param>
		/// <param name="handler">要订阅的事件处理函数</param>
		public void Subscribe(int id, EventHandler<GameEventAgrs> handler)
		{
			m_EventPool.Subscribe(id, handler);
		}

		/// <summary>
		/// 取消订阅事件处理函数
		/// </summary>
		/// <param name="id">事件类型编号</param>
		/// <param name="handler">要取消订阅的事件处理函数</param>
		public void Unsubscribe(int id, EventHandler<GameEventAgrs> handler)
		{
			m_EventPool.Unsubscribe(id, handler);
		}

		/// <summary>
		/// 抛出事件，这个操作是线程安全的，即使不在主线程中抛出，也可保证在主线程中回调事件处理函数，但事件会在抛出后的下一帧分发。
		/// </summary>
		/// <param name="sender">事件源。</param>
		/// <param name="e">事件参数。</param>
		public void Fire(object sender, GameEventAgrs e)
		{
			m_EventPool.Fire(sender, e);
		}

		/// <summary>
		/// 抛出事件立即模式，这个操作不是线程安全的，事件会立即分发
		/// </summary>
		/// <param name="sender">事件源</param>
		/// <param name="e">事件参数</param>
		public void FireNow(object sender, GameEventAgrs e)
		{
			m_EventPool.FireNow(sender, e);
		}
	}
}
